package c2.cross.business.rank.core;

import c2.cross.business.base.CrossSubModule;
import c2.cross.business.rank.CrossRankModule;
import c2.cross.business.rank.h.BaseExtraValueRankHandler;
import c2.cross.business.rank.h.BaseSingleValueRankHandler;
import c2.cross.business.rank.h.GuildCrossRankHandler;
import c2.cross.business.rank.h.ICrossRankHandler;
import c2.cross.business.rank.manager.CrossRankActivityManager;
import c2.cross.business.rank.manager.CrossRankPermanentManager;
import cate.game.rank.cross.CrossRankMsg;
import cate.game.rank.po.GuildRank;
import cate.game.rank.po.Rank;
import cate.game.res.holy_pet.HolyPetConstants;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

import static cate.game.rank.cross.CrossRankMessageModule.*;

@Slf4j
public class CrossRankDataModule extends CrossSubModule<CrossRankModule> {
    public final CrossRankPermanentManager permanents = new CrossRankPermanentManager();
    public final CrossRankActivityManager activities = new CrossRankActivityManager();

    @Override
    public void initDependent() {
        // 加载常量
        HolyPetConstants.loadFromTable(useTable().common);
        permanents.init(parent);
        activities.init(parent);
        useRpcRecv().onRequestResponseTemplate(CrossRankMsg.GET_RANK_LIST, CrossRankRoleGetListReq.class,
                (h, req) -> getRoleRankList(req.roleUid, req.rankId, req.limit, req.forceLoad));
        useRpcRecv().onRequestResponseTemplate(CrossRankMsg.GET_GUILD_RANK_LIST, CrossRankGuildGetListReq.class,
                (h, req) -> getGuildRankList(req.guildUid, req.limit, req.forceLoad));
        useRpcRecv().onFireAndForgetTemplate(CrossRankMsg.UPDATE_ROLE_RECORD, UpdateRoleRecord.class, (h, req) -> {
            ICrossRankHandler handler = findHandler(req.rankId);
            if (handler != null) {
                if (handler instanceof BaseExtraValueRankHandler) {
                    ((BaseExtraValueRankHandler) handler).record(req.snapshot, req.newValue, req.newExtraValue);
                } else if (handler instanceof BaseSingleValueRankHandler) {
                    ((BaseSingleValueRankHandler) handler).record(req.snapshot, req.newValue);
                }
            }
        });
        useRpcRecv().onFireAndForgetTemplate(CrossRankMsg.UPDATE_GUILD_RECORD, UpdateGuildRecord.class, (h, req) -> {
            GuildCrossRankHandler handler = findGuildHandler();
            if (handler != null) {
                handler.record(req);
            }
        });
    }

    /**
     * 获取角色看到的列表
     *
     * @param roleUid   角色ID
     * @param rankId    排行榜类型
     * @param limit     限制数量
     * @param forceLoad 是否强制拉取新列表
     * @return 获取结果
     */
    public CrossRankRoleGetListResp getRoleRankList(String roleUid, int rankId, int limit, boolean forceLoad) {
        CrossRankRoleGetListResp resp = new CrossRankRoleGetListResp();
        try {
            ICrossRankHandler handler = findHandler(rankId);
            if (handler == null) {
                resp.fail("排行榜未开启");
                return resp;
            }
            int myRank = handler.getRankIndex(roleUid);
            Rank self = handler.findRankByRoleUid(roleUid);
            List<Rank> list = null;
            if (forceLoad || (myRank > 0 && myRank <= limit)) {
                list = handler.getRankList(limit);
            }
            resp.roleUid = roleUid;
            resp.myRank = myRank;
            resp.self = self;
            resp.list = list;
        } catch (Exception e) {
            log.error("", e);
            resp.fail("Error");
        }
        return resp;
    }

    /**
     * 获取角色看到的列表
     *
     * @param guildUid   协会ID
     * @param limit     限制数量
     * @param forceLoad 是否强制拉取新列表
     * @return 获取结果
     */
    public CrossRankGuildGetListResp getGuildRankList(String guildUid, int limit, boolean forceLoad) {
        CrossRankGuildGetListResp resp = new CrossRankGuildGetListResp();
        try {
            GuildCrossRankHandler handler = findGuildHandler();
            if (handler == null) {
                resp.fail("排行榜未开启");
                return resp;
            }
            int myRank = handler.getRankIndex(guildUid);
            GuildRank self = handler.findRankByGuildUid(guildUid);
            List<GuildRank> list = null;
            if (forceLoad || (myRank > 0 && myRank <= limit)) {
                list = handler.getRankList(limit);
            }
            resp.guildUid = guildUid;
            resp.myRank = myRank;
            resp.self = self;
            resp.list = list;
        } catch (Exception e) {
            log.error("", e);
            resp.fail("Error");
        }
        return resp;
    }

    private ICrossRankHandler findHandler(int rankId) {
        if (permanents.focusRankId(rankId)) {
            return permanents.tryGetCrossSingleRankHandler(rankId).orElse(null);
        } else if (activities.focusRankId(rankId)) {
            return activities.tryGetCrossSingleRankHandler(rankId).orElse(null);
        }
        return null;
    }

    private GuildCrossRankHandler findGuildHandler() {
        return permanents.getGuildHandler();
    }

    @Override
    public void onInterval() {
        permanents.safeTick();
        activities.safeTick();
    }

    @Override
    public void onShutdown() {
        permanents.save();
        activities.save();
    }
}
